package com.yanfan.energy.service.impl;

import com.yanfan.common.exception.base.BaseException;
import com.yanfan.common.utils.StringUtils;
import com.yanfan.energy.domain.OrderSequence;
import com.yanfan.energy.domain.TreeNode;
import com.yanfan.energy.domain.statist.CompanyBuildArea;
import com.yanfan.energy.domain.statist.CompanyBuildAreaEntity;
import com.yanfan.energy.mapper.BuildServiceDao;
import com.yanfan.energy.service.BuildService;
import com.yanfan.energy.service.ExcelService;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

/**
 * @Author huan
 * @Description 楼栋楼层区域Service
 * @ClassName 2023年07月28日 09:18:00
 * @Version 1.0
 **/
@Service
@Transactional(rollbackFor = Exception.class)
public class BuildServiceImpl implements BuildService {


    @Resource
    BuildServiceDao buildServiceDao;

    @Autowired
    private ExcelService excelService;

    /**
     * 设备区域相关
     *
     * @return
     */
    @Override
    public List<CompanyBuildArea> deviceLocation(CompanyBuildArea companyBuildArea) {
        if (companyBuildArea.getType() == null) {
            throw new BaseException("查询type类型不能为空 对应枚举值信息为 公司 1 ， 楼栋 2， 楼层 3  区域 4");
        }
        return buildServiceDao.deviceLocationList(companyBuildArea);
    }


    /**
     * 添加
     *
     * @param companyBuildArea
     */
    @Override
    public void deviceLocationAdd(CompanyBuildArea companyBuildArea) {
        verifyParamAddOrUpdate(companyBuildArea, false);
        buildServiceDao.deviceLocationAdd(companyBuildArea);
    }

    /**
     * 修改文件
     *
     * @param companyBuildArea
     */
    @Override
    public void deviceLocationUpdate(CompanyBuildArea companyBuildArea) {
        verifyParamAddOrUpdate(companyBuildArea, true);
        // 修改之前需要把
        buildServiceDao.deviceLocationUpdate(companyBuildArea);
    }

    @Override
    public void deviceLocationDelete(CompanyBuildArea companyBuildArea) {
        if (companyBuildArea.getType() == null) {
            throw new BaseException("查询type类型不能为空 对应枚举值信息为 公司 1 ， 楼栋 2， 楼层 3  区域 4");
        }
        verifyParamDetailOrDelete(companyBuildArea);
        // 删除，要把该节点下的所有删除
        buildServiceDao.deviceLocationDelete(companyBuildArea);
    }


    @Override
    public CompanyBuildArea deviceLocationDetail(CompanyBuildArea companyBuildArea) {
        if (companyBuildArea.getType() == null) {
            throw new BaseException("查询type类型不能为空 对应枚举值信息为 公司 1 ， 楼栋 2， 楼层 3  区域 4");
        }

        verifyParamDetailOrDelete(companyBuildArea);

        return buildServiceDao.deviceLocationDetail(companyBuildArea);
    }

    private void verifyParamDetailOrDelete(CompanyBuildArea companyBuildArea) {
        // 公司
        if (companyBuildArea.getType().equals(1)) {
            if (companyBuildArea.getCompanyId() == null) {
                throw new BaseException("公司id不能为空");
            }
        }
        // 楼栋
        if (companyBuildArea.getType().equals(2)) {
            if (companyBuildArea.getBuildId() == null) {
                throw new BaseException("楼栋 id不能为空");
            }
        }
        // 楼层
        if (companyBuildArea.getType().equals(3)) {
            if (companyBuildArea.getFloorId() == null) {
                throw new BaseException("楼层 id不能为空");
            }
        }
        // 区域
        if (companyBuildArea.getType().equals(4)) {
            if (companyBuildArea.getAreaId() == null) {
                throw new BaseException("区域 id不能为空");
            }
        }
    }

    private void verifyParamAddOrUpdate(CompanyBuildArea companyBuildArea, boolean updateFlag) {
        if (companyBuildArea.getType() == null) {
            throw new BaseException("查询type类型不能为空 对应枚举值信息为 公司 1 ， 楼栋 2， 楼层 3  区域 4");
        }

        // 公司
        if (companyBuildArea.getType().equals(1)) {
            if (updateFlag && companyBuildArea.getCompanyId() == null) {
                throw new BaseException("公司id不能为空");
            }
            if (StringUtils.isEmpty(companyBuildArea.getCompanyName())) {
                throw new BaseException("公司id、公司名称不能为空");
            }
            if (!updateFlag) {
                OrderSequence orderSequence = new OrderSequence();
                buildServiceDao.sequenceNext(orderSequence);
                companyBuildArea.setCompanyId(orderSequence.getId());
            }
        }
        // 楼栋
        else if (companyBuildArea.getType().equals(2)) {
            if (companyBuildArea.getCompanyId() == null) {
                throw new BaseException("公司id不能为空");
            }
            CompanyBuildArea request = new CompanyBuildArea();
            request.setCompanyId(companyBuildArea.getCompanyId());
            request.setType(1);
            // 判断公司是否存在
            CompanyBuildArea resEntity = buildServiceDao.deviceLocationDetail(request);
            if (resEntity == null) {
                throw new BaseException("公司不存在");
            }
            if (updateFlag && companyBuildArea.getBuildId() == null) {
                throw new BaseException(" 楼栋id不能为空");
            }
            if (updateFlag && companyBuildArea.getCompanyId() == null) {
                throw new BaseException(" 公司id不能为空");
            }
            if (updateFlag && companyBuildArea.getBuildName() == null) {
                throw new BaseException(" 楼栋名称不能为空");
            }
            if (!updateFlag) {
                OrderSequence orderSequence = new OrderSequence();
                buildServiceDao.sequenceNext(orderSequence);
                companyBuildArea.setBuildId(orderSequence.getId());
            }
//            if (StringUtils.isEmpty(companyBuildArea.getBuildName())) {
//                throw new BaseException("楼栋名称不能为空");
//            }

        }
        // 楼层
        else if (companyBuildArea.getType().equals(3)) {
            if (companyBuildArea.getFloorName() == null) {
                throw new BaseException("楼层名称 不能为空");
            }
            if (companyBuildArea.getBuildId() == null) {
                throw new BaseException("楼栋id不能为空");
            }
            CompanyBuildArea request = new CompanyBuildArea();
            request.setBuildId(companyBuildArea.getBuildId());
            request.setType(2);
            // 判断公司是否存在
            CompanyBuildArea resEntity = buildServiceDao.deviceLocationDetail(request);
            if (resEntity == null) {
                throw new BaseException("楼栋id 不存在");
            }
//            if (!resEntity.getCompanyId().equals(companyBuildArea.getCompanyId())) {
//                throw new BaseException("公司id 不存在");
//            }
            if (updateFlag && companyBuildArea.getFloorId() == null) {
                throw new BaseException("楼层id不能为空");
            }

//            if (StringUtils.isEmpty(companyBuildArea.getFloorName())) {
//                throw new BaseException("楼层 名称不能为空");
//            }

            if (!updateFlag) {
                OrderSequence orderSequence = new OrderSequence();
                buildServiceDao.sequenceNext(orderSequence);
                companyBuildArea.setFloorId(orderSequence.getId());
            }
        }
        // 区域
        else if (companyBuildArea.getType().equals(4)) {
//            if(companyBuildArea.getCompanyId()==null){
//                throw new BaseException("公司id不能为空");
//            }
            if (companyBuildArea.getAreaName() == null) {
                throw new BaseException("areaName 区域名称 不能为空");
            }
//            if(companyBuildArea.getBuildId()==null){
//                throw new BaseException("楼栋id不能为空");
//            }
            if (companyBuildArea.getFloorId() == null) {
                throw new BaseException("楼层id不能为空");
            }
            CompanyBuildArea request = new CompanyBuildArea();
            request.setFloorId(companyBuildArea.getFloorId());
            request.setType(3);
            // 判断公司是否存在
            CompanyBuildArea resEntity = buildServiceDao.deviceLocationDetail(request);
            if (resEntity == null) {
                throw new BaseException("楼栋id 不存在");
            }
            if (updateFlag && companyBuildArea.getAreaId() == null) {
                throw new BaseException("区域id不能为空");
            }
            if (updateFlag && companyBuildArea.getFloorId() == null) {
                throw new BaseException("楼层 id不能为空");
            }
            if (StringUtils.isEmpty(companyBuildArea.getAreaName())) {
                throw new BaseException("区域名称不能为空");
            }

            if (!updateFlag) {
                OrderSequence orderSequence = new OrderSequence();
                buildServiceDao.sequenceNext(orderSequence);
                companyBuildArea.setAreaId(orderSequence.getId());
            }

        }
    }


    @Override
    public List<TreeNode> deviceLocationDeptTree() {
        // 查询公司列表
        CompanyBuildArea companyBuildArea = new CompanyBuildArea();
        companyBuildArea.setType(1);
        List<CompanyBuildArea> companyList = buildServiceDao.deviceLocationList(companyBuildArea);
        if (CollectionUtils.isEmpty(companyList)) {
            return new ArrayList<>();
        }
        // 构建树形结构
        List<TreeNode> treeNodes = new ArrayList<>();
        // 公司
        for (CompanyBuildArea company : companyList) {
            TreeNode companyNode = new TreeNode(company.getCompanyId(), company.getCompanyName(), 1);
            CompanyBuildArea buildQuery = new CompanyBuildArea();
            buildQuery.setType(2);
            buildQuery.setCompanyId(company.getCompanyId());
            List<CompanyBuildArea> buildList = buildServiceDao.deviceLocationList(buildQuery);
            if (CollectionUtils.isEmpty(companyList)) {
                continue;
            }
            // 楼栋
            for (CompanyBuildArea build : buildList) {
                TreeNode buildNode = new TreeNode(build.getBuildId(), build.getBuildName(), 2);
                CompanyBuildArea floorQuery = new CompanyBuildArea();
                floorQuery.setType(3);
                floorQuery.setBuildId(build.getBuildId());
                List<CompanyBuildArea> floorList = buildServiceDao.deviceLocationList(floorQuery);
                if (CollectionUtils.isEmpty(companyList)) {
                    continue;
                }
                // 楼层
                for (CompanyBuildArea floor : floorList) {
                    TreeNode floorNode = new TreeNode(floor.getFloorId(), floor.getFloorName(), 3);
                    CompanyBuildArea areaQuery = new CompanyBuildArea();
                    areaQuery.setType(4);
                    areaQuery.setFloorId(floor.getFloorId());
                    List<CompanyBuildArea> areaList = buildServiceDao.deviceLocationList(areaQuery);
                    if (CollectionUtils.isEmpty(areaList)) {
                        continue;
                    }
                    for (CompanyBuildArea area : areaList) {
                        TreeNode areaNode = new TreeNode(area.getAreaId(), area.getAreaName(), 4);
                        floorNode.addChild(areaNode);
                    }

                    buildNode.addChild(floorNode);
                }

                companyNode.addChild(buildNode);

            }

            treeNodes.add(companyNode);
        }

//        List<>
        return treeNodes;
    }

    //  上面的可以考虑删除

//    @Override
//    public List<CompanyBuildAreaEntity> selectCompanyBuildAreaList(Integer status,String name) {
//        CompanyBuildAreaEntity entity = new CompanyBuildAreaEntity();
//        entity.setType(1);
////        entity.setName(name);
////        entity.setStatus(status);
//        List<CompanyBuildAreaEntity> companyList = buildServiceDao.selectCompanyBuildAreaList(entity);
//        if (CollectionUtils.isEmpty(companyList)) {
//            return new ArrayList<>();
//        }
//        for (CompanyBuildAreaEntity company : companyList) {
//            CompanyBuildAreaEntity buildEntity = new CompanyBuildAreaEntity();
//            buildEntity.setType(2);
//            buildEntity.setParentId(company.getId());
////            buildEntity.setName(name);
////            buildEntity.setStatus(status);
//            List<CompanyBuildAreaEntity> buildList = buildServiceDao.selectCompanyBuildAreaList(buildEntity);
//            if (CollectionUtils.isEmpty(buildList)) {
//                continue;
//            }
//            for (CompanyBuildAreaEntity build : buildList) {
//                CompanyBuildAreaEntity floorEntity = new CompanyBuildAreaEntity();
//                floorEntity.setType(3);
//                floorEntity.setParentId(build.getId());
////                floorEntity.setName(name);
////                floorEntity.setStatus(status);
//                List<CompanyBuildAreaEntity> floorList = buildServiceDao.selectCompanyBuildAreaList(floorEntity);
//                if (CollectionUtils.isEmpty(floorList)) {
//                    continue;
//                }
//                for (CompanyBuildAreaEntity floor : floorList) {
//                    CompanyBuildAreaEntity areaEntity = new CompanyBuildAreaEntity();
//                    areaEntity.setType(4);
//                    areaEntity.setParentId(floor.getId());
////                    areaEntity.setName(name);
////                    areaEntity.setStatus(status);
//                    floor.setChildren(buildServiceDao.selectCompanyBuildAreaList(areaEntity));
//                }
//                build.setChildren(floorList);
//            }
//
//            company.setChildren(buildList);
//        }
//
//        return companyList;
//    } public List<CompanyBuildAreaEntity> selectCompanyBuildAreaList(Integer status,String name) {
//        CompanyBuildAreaEntity entity = new CompanyBuildAreaEntity();
//        entity.setType(1);
////        entity.setName(name);
////        entity.setStatus(status);
//        List<CompanyBuildAreaEntity> companyList = buildServiceDao.selectCompanyBuildAreaList(entity);
//        if (CollectionUtils.isEmpty(companyList)) {
//            return new ArrayList<>();
//        }
//        for (CompanyBuildAreaEntity company : companyList) {
//            CompanyBuildAreaEntity buildEntity = new CompanyBuildAreaEntity();
//            buildEntity.setType(2);
//            buildEntity.setParentId(company.getId());
////            buildEntity.setName(name);
////            buildEntity.setStatus(status);
//            List<CompanyBuildAreaEntity> buildList = buildServiceDao.selectCompanyBuildAreaList(buildEntity);
//            if (CollectionUtils.isEmpty(buildList)) {
//                continue;
//            }
//            for (CompanyBuildAreaEntity build : buildList) {
//                CompanyBuildAreaEntity floorEntity = new CompanyBuildAreaEntity();
//                floorEntity.setType(3);
//                floorEntity.setParentId(build.getId());
////                floorEntity.setName(name);
////                floorEntity.setStatus(status);
//                List<CompanyBuildAreaEntity> floorList = buildServiceDao.selectCompanyBuildAreaList(floorEntity);
//                if (CollectionUtils.isEmpty(floorList)) {
//                    continue;
//                }
//                for (CompanyBuildAreaEntity floor : floorList) {
//                    CompanyBuildAreaEntity areaEntity = new CompanyBuildAreaEntity();
//                    areaEntity.setType(4);
//                    areaEntity.setParentId(floor.getId());
////                    areaEntity.setName(name);
////                    areaEntity.setStatus(status);
//                    floor.setChildren(buildServiceDao.selectCompanyBuildAreaList(areaEntity));
//                }
//                build.setChildren(floorList);
//            }
//
//            company.setChildren(buildList);
//        }
//
//        return companyList;
//    }


    @Override
    public List<CompanyBuildAreaEntity> selectCompanyBuildAreaList(Integer status, String name) {
        List<CompanyBuildAreaEntity> list = new ArrayList<>();
        setCompanyBuildAreaEntity(status, name, list, 1);
        setCompanyBuildAreaEntity(status, name, list, 2);
        setCompanyBuildAreaEntity(status, name, list, 3);
        setCompanyBuildAreaEntity(status, name, list, 4);
        return buildAreaTree(list, status, name);
    }

    /**
     * 楼栋 楼层 区域 公司
     *
     * @param status
     * @param name
     * @param list
     * @param type
     */
    private void setCompanyBuildAreaEntity(Integer status, String name, List<CompanyBuildAreaEntity> list, Integer type) {
        CompanyBuildAreaEntity entity = new CompanyBuildAreaEntity();
        entity.setType(type);
        entity.setName(name);
        entity.setStatus(status);
        List<CompanyBuildAreaEntity> companyList = buildServiceDao.selectCompanyBuildAreaAll(entity);
        if (!CollectionUtils.isEmpty(companyList)) {
            list.addAll(companyList);
        }
    }


    private List<CompanyBuildAreaEntity> buildAreaTree(List<CompanyBuildAreaEntity> list, Integer status, String name) {

        List<CompanyBuildAreaEntity> treeList = parseToTree(list);
        return treeList;
    }

    private List<CompanyBuildAreaEntity> parseToTree(List<CompanyBuildAreaEntity> entities) {
        Map<Long, CompanyBuildAreaEntity> entityMap = new HashMap<>();

        // Build a map of entities using their IDs as keys
        for (CompanyBuildAreaEntity entity : entities) {
            entityMap.put(entity.getId(), entity);
        }

        List<CompanyBuildAreaEntity> returnList = new ArrayList<>();

        // Traverse the entities and add them to the parent's children list
        for (CompanyBuildAreaEntity entity : entities) {
            Integer typeN = entity.getType() - 1;
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!(entityMap.keySet().contains(entity.getParentId()) && entityMap
                    .get(entity.getParentId())
                    .getType() == typeN)) {
                recursionFn(entities, entity);
                returnList.add(entity);
            }

            if (returnList.isEmpty()) {
                returnList = entities;
            }


        }
        return returnList;
    }

    private void recursionFn(List<CompanyBuildAreaEntity> list, CompanyBuildAreaEntity t) {
        // 得到子节点列表
        List<CompanyBuildAreaEntity> childList = getChildList(list, t);
        t.setChildren(childList);
        for (CompanyBuildAreaEntity tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }

    private boolean hasChild(List<CompanyBuildAreaEntity> list, CompanyBuildAreaEntity tChild) {
        return getChildList(list, tChild).size() > 0;
    }

    private List<CompanyBuildAreaEntity> getChildList(List<CompanyBuildAreaEntity> list, CompanyBuildAreaEntity t) {
        List<CompanyBuildAreaEntity> tlist = new ArrayList<CompanyBuildAreaEntity>();
        Iterator<CompanyBuildAreaEntity> it = list.iterator();
        while (it.hasNext()) {
            CompanyBuildAreaEntity n = (CompanyBuildAreaEntity) it.next();
            Integer nType = n.getType() - 1;
            if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().longValue() == t
                    .getId()
                    .longValue() && nType.equals(t.getType())) {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 添加楼栋楼层相关
     *
     * @param entity
     */
    @Override
    public void addCompanyBuildArea(CompanyBuildAreaEntity entity) {
        // 判断是不是公司
        if (entity.getType() == null) {
            throw new BaseException("type 不为null");
        }
        // 公司
        if (entity.getType().equals(1)) {
            // 添加公司
            entity.setId(orderId());
            double buildArea = entity.getArea();
            entity.setArea(0.0);
            buildServiceDao.addCompanyBuildArea(entity);
            // 添加楼栋
            CompanyBuildAreaEntity build = new CompanyBuildAreaEntity();
            build.setType(2);
            build.setStatus(1);
            build.setId(orderId());
            build.setName(entity.getBuildName());
            build.setArea(buildArea);
            build.setParentId(entity.getId());
            buildServiceDao.addCompanyBuildArea(build);
        } else {
            entity.setId(orderId());
            entity.setBuildingId(buildServiceDao.getbuildingId(entity.getParentId()));
            buildServiceDao.addCompanyBuildArea(entity);
        }
    }

    public Long orderId() {
        OrderSequence orderSequence = new OrderSequence();
        buildServiceDao.sequenceNext(orderSequence);
        return orderSequence.getId();
    }

    @Override
    public void updateCompanyBuildArea(CompanyBuildAreaEntity entity) {
        buildServiceDao.updateCompanyBuildArea(entity);
    }

    @Override
    public void deleteCompanyBuildArea(CompanyBuildAreaEntity entity) {
        buildServiceDao.deleteCompanyBuildArea(entity);
    }

    @Override
    public CompanyBuildAreaEntity detailCompanyBuildArea(CompanyBuildAreaEntity entity) {
        return buildServiceDao.detailCompanyBuildArea(entity);
    }

    @Override
    public void export(HttpServletResponse response, Integer status, String name) throws IOException {
        List<CompanyBuildAreaEntity> companyBuildAreaEntities = selectCompanyBuildAreaList(status, name);
        ExcelExporter.exportToExcel(companyBuildAreaEntities, response);
    }

    @Override
    public List<CompanyBuildAreaEntity> findFloorsByBuilds(Integer[] buildIds) {
        return buildServiceDao.findFloorsByBuilds(buildIds);
    }

    @Override
    public List<CompanyBuildAreaEntity> findAreaByFloors(Integer[] floorIds) {
        return buildServiceDao.findAreaByFloors(floorIds);
    }
}
